home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / Amiga_Mail_Vol2 / Archives / Plain / mj91 / ImageClass / mytextlabelclass.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-12  |  12.1 KB  |  471 lines

  1. /*
  2.  * mytextlabelclass.c Copyright (C) 1991 Commodore-Amiga, Inc. All Rights Reserved Worldwide
  3.  * The information contained herein is subject to change without notice,
  4.  * and is provided "as is" without warranty of any kind, either expressed
  5.  * or implied.  The entire risk as to the use of this information is
  6.  * assumed by the user.
  7.  * 
  8.  * Written by David N. Junod
  9.  *
  10.  * Compiled with SAS/C 5.10a LC -cfist -ms -v (must be linked with classface.o and
  11.  * hookface.o)
  12.  *
  13.  * The Image structure as used by this class:
  14.  *
  15.  * struct Image {
  16.  *
  17.  * SHORT    LeftEdge;        <----Offset relative to the container
  18.  * SHORT    TopEdge;
  19.  *
  20.  * SHORT    Width;           <----Contains the text extent of the string
  21.  * SHORT    Height;
  22.  *
  23.  * SHORT    Depth;           <----Maintained by boopsi (must be set to CUSTOMIMAGEDEPTH).
  24.  *
  25.  * USHORT   *ImageData;      <----Pointer to a NULL terminated text string
  26.  *
  27.  * UBYTE    PlanePick;       <----We use this for the foreground color
  28.  *
  29.  * UBYTE    PlaneOnOff;      <----We use this for the background color
  30.  *
  31.  * struct Image *NextImage;  <----Pointer to the next image.  Handled by DrawImage(). };
  32.  */
  33.  
  34.  
  35. #include <exec/types.h>
  36. #include <exec/memory.h>
  37. #include <exec/libraries.h>
  38. #include <intuition/intuition.h>
  39. #include <intuition/classes.h>
  40. #include <intuition/classusr.h>
  41. #include <intuition/cghooks.h>
  42. #include <intuition/gadgetclass.h>
  43. #include <intuition/imageclass.h>
  44. #include <intuition/icclass.h>
  45. #include <intuition/screens.h>
  46. #include <graphics/gfx.h>
  47. #include <graphics/gfxmacros.h>
  48. #include <libraries/gadtools.h>
  49. #include <utility/tagitem.h>
  50. #include <clib/macros.h>
  51. #include <clib/exec_protos.h>
  52. #include <clib/intuition_protos.h>
  53. #include <clib/graphics_protos.h>
  54. #include <clib/utility_protos.h>
  55. #include <string.h>
  56.  
  57. extern struct Library *SysBase, *DOSBase;
  58. extern struct Library *IntuitionBase, *GfxBase, *UtilityBase;
  59.  
  60. /*
  61.  * Because we are dealing with imageclass objects, the data structure that makes up the
  62.  * object is an intuition Image structure.
  63.  */
  64. #define IM(o)   ((struct Image *)(o))
  65.  
  66. #define MYCLASSID       NULL
  67. #define SUPERCLASSID    (IMAGECLASS)
  68.  
  69. Class          *initmyTextLabelClass(VOID);
  70. ULONG           freemyTextLabelClass(Class * cl);
  71. ULONG __saveds  dispatchmyTextLabel(Class * cl, Object * o, Msg msg);
  72. ULONG           setmyTextLabelAttrs(Class * cl, Object * o, struct opSet * msg);
  73. ULONG           getmyTextLabelAttr(Class * cl, Object * o, struct opGet * msg);
  74. ULONG           drawmyTextLabel(Class * cl, Object * o, struct impDraw * msg);
  75. WORD            aTextExtent(struct RastPort *, STRPTR, LONG, struct TextExtent *);
  76. UWORD           GetLabelKeystroke(STRPTR label);
  77. static VOID     getContentsExtent(Class * cl, Object * o, struct DrawInfo * drinfo);
  78.  
  79. /* prototypes of functions from classface.o */
  80. ULONG           DoMethod(Object * o, ULONG methodID,...);
  81. ULONG           DoSuperMethod(Class * cl, Object * o, ULONG methodID,...);
  82. ULONG           CoerceMethod(Class * cl, Object * o, ULONG methodID,...);
  83. ULONG           CM(Class * cl, Object * o, Msg msg);
  84. ULONG           DM(Object * o, Msg msg);
  85. ULONG           DSM(Class * cl, Object * o, Msg msg);
  86. ULONG           SetSuperAttrs(Class * cl, Object * o, ULONG data,...);
  87.  
  88. struct localObjData
  89. {
  90.     /* Font to use */
  91.     struct TextFont *lod_Font;
  92.  
  93.     /* The key that is underlined */
  94.     UWORD           lod_Key;
  95.  
  96.     /* DrawMode */
  97.     UBYTE           lod_Mode;
  98. };
  99.  
  100.  
  101. Class          *
  102. initmyTextLabelClass(VOID)
  103. {
  104.     ULONG           hookEntry(); /* from hookface.o */
  105.     Class          *cl;
  106.  
  107.     if (cl = MakeClass(MYCLASSID,
  108.                        SUPERCLASSID, NULL,
  109.                        sizeof(struct localObjData), 0))
  110.     {
  111.         /* Fill in the callback hook */
  112.         cl->cl_Dispatcher.h_Entry = hookEntry;
  113.         cl->cl_Dispatcher.h_SubEntry = dispatchmyTextLabel;
  114.     }
  115.     /* Return a pointer to the class */
  116.     return (cl);
  117. }
  118.  
  119.  
  120. ULONG
  121. freemyTextLabelClass(Class * cl)
  122. {
  123.  
  124.     /* Try to free the public class */
  125.     return ((ULONG) FreeClass(cl));
  126. }
  127.  
  128.  
  129. /*
  130.  * The SAS "__saveds" flag tells the SAS compiler to put
  131.  * the data storage address + 32766 into A4.
  132.  */
  133. ULONG           __saveds
  134. dispatchmyTextLabel(Class * cl, Object * o, Msg msg)
  135. {
  136.     struct localObjData *lod;
  137.     Object         *newobj;
  138.     ULONG           retval;
  139.  
  140.     switch (msg->MethodID)
  141.     {
  142.     case OM_NEW:
  143.         /* Pass up to the superclass... */
  144.         if (newobj = (Object *) DSM(cl, o, msg))
  145.         {
  146.             struct TagItem *attrs = ((struct opSet *) msg)->ops_AttrList;
  147.             struct DrawInfo *drinfo;
  148.  
  149.             /* Get the DrawInfo */
  150.             drinfo = (struct DrawInfo *) GetTagData(SYSIA_DrawInfo, NULL, attrs);
  151.  
  152.             /* Get the instance data */
  153.             lod = INST_DATA(cl, newobj);
  154.  
  155.             /* Establish defaults */
  156.             IM(newobj)->PlanePick = 1;
  157.             lod->lod_Mode = JAM1;
  158.  
  159.             /* Set the attributes */
  160.             setmyTextLabelAttrs(cl, newobj, (struct opSet *) msg);
  161.  
  162.             /* Get the bounding rectangle of the label */
  163.             getContentsExtent(cl, newobj, drinfo);
  164.         }
  165.         retval = (ULONG) newobj;
  166.         break;
  167.  
  168.     case OM_GET:
  169.         retval = getmyTextLabelAttr(cl, o, (struct opGet *) msg);
  170.         break;
  171.  
  172.     case OM_UPDATE:
  173.     case OM_SET:
  174.         /* Do the superclass first */
  175.         retval = DSM(cl, o, msg);
  176.  
  177.         /* Call our set routines */
  178.         retval += setmyTextLabelAttrs(cl, o, (struct opSet *) msg);
  179.         break;
  180.  
  181.     case IM_DRAW:               /* draw the label */
  182.     case IM_DRAWFRAME:          /* drawmyTextLabel() will take care of 
  183.                                    extra framing info */
  184.         retval = drawmyTextLabel(cl, o, (struct impDraw *) msg);
  185.         break;
  186.  
  187.     /* Let the superclass handle everything else */
  188.     default:
  189.         retval = (ULONG) DSM(cl, o, msg);
  190.         break;
  191.     }
  192.  
  193.     return (retval);
  194. }
  195.  
  196.  
  197. /* Set attributes of an object */
  198. ULONG
  199. setmyTextLabelAttrs(Class * cl, Object * o, struct opSet * msg)
  200. {
  201.     struct localObjData *lod = INST_DATA(cl, o);
  202.     struct TagItem *tags = msg->ops_AttrList;
  203.     struct TagItem *tstate;
  204.     struct TagItem *tag;
  205.     ULONG           tidata;
  206.  
  207.     /* process rest */
  208.     tstate = tags;
  209.     while (tag = NextTagItem(&tstate))
  210.     {
  211.         tidata = tag->ti_Data;
  212.         switch (tag->ti_Tag)
  213.         {
  214.         case IA_FGPen:
  215.             IM(o)->PlanePick = (UBYTE) tidata;
  216.             break;
  217.  
  218.         case IA_BGPen:
  219.             IM(o)->PlaneOnOff = (UBYTE) tidata;
  220.             break;
  221.  
  222.             /* Must be a TextFont pointer. */
  223.         case IA_Font:
  224.             /* Set the font */
  225.             lod->lod_Font = (struct TextFont *) tidata;
  226.             break;
  227.  
  228.             /* Drawing mode to use */
  229.         case IA_Mode:
  230.             lod->lod_Mode = (UBYTE) tidata;
  231.             break;
  232.  
  233.         case IA_Data:
  234.             IM(o)->ImageData = (USHORT *) tidata;
  235.             lod->lod_Key = GetLabelKeystroke((STRPTR) tidata);
  236.             break;
  237.         }
  238.     }
  239.  
  240.     return (1L);
  241. }
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248. /* Inquire attributes of an object */
  249. ULONG
  250. getmyTextLabelAttr(Class * cl, Object * o, struct opGet * msg)
  251. {
  252.     struct localObjData *lod = INST_DATA(cl, o);
  253.  
  254.     switch (msg->opg_AttrID)
  255.     {
  256.     case IA_Font:
  257.         *msg->opg_Storage = (ULONG) lod->lod_Font;
  258.         break;
  259.  
  260.     case IA_Mode:
  261.         *msg->opg_Storage = (ULONG) lod->lod_Mode;
  262.         break;
  263.  
  264.         /* Let the superclass try */
  265.     default:
  266.         return ((ULONG) DSM(cl, o, msg));
  267.     }
  268.  
  269.     return (1L);
  270. }
  271.  
  272.  
  273. ULONG
  274. drawmyTextLabel(Class * cl, Object * o, struct impDraw * msg)
  275. {
  276.     struct localObjData *lod = INST_DATA(cl, o);
  277.     STRPTR          label = (STRPTR) IM(o)->ImageData;
  278.     struct DrawInfo *di = msg->imp_DrInfo;
  279.     struct RastPort *rp = msg->imp_RPort;
  280.     struct TextFont *tf = NULL;
  281.     WORD            len = strlen(label);
  282.     WORD            left, top;
  283.     WORD            height = 0;
  284.     WORD            width = 0;
  285.     WORD            i;
  286.  
  287.     /* Clear the key */
  288.     lod->lod_Key = NULL;
  289.  
  290.     /* Get a pointer to the font to use */
  291.     if (!(tf = lod->lod_Font) && di)
  292.     {
  293.         tf = di->dri_Font;
  294.     }
  295.  
  296.     /* Make sure we have font pointer */
  297.     if (tf)
  298.     {
  299.         /* Set the font */
  300.         SetFont(rp, tf);
  301.     }
  302.     /* Figure out our coordinates */
  303.     top = msg->imp_Offset.Y + IM(o)->TopEdge + rp->TxBaseline;
  304.     left = msg->imp_Offset.X + IM(o)->LeftEdge;
  305.  
  306.     /* See if we have frame information. */
  307.     if (msg->MethodID == IM_DRAWFRAME)
  308.     {
  309.         /* Center the text inside the frame. */
  310.         width = msg->imp_Dimensions.Width;
  311.         height = msg->imp_Dimensions.Height;
  312.         top += ((height - IM(o)->Height) > 0) ? ((height - IM(o)->Height) / 2) : 0;
  313.         left += ((width - IM(o)->Width) > 0) ? ((width - IM(o)->Width) / 2) : 0;
  314.     }
  315.  
  316.     /* Set the colors */
  317.     SetAPen(rp, IM(o)->PlanePick);
  318.     SetBPen(rp, IM(o)->PlaneOnOff);
  319.  
  320.     /* Set the drawing mode */
  321.     SetDrMd(rp, lod->lod_Mode);
  322.  
  323.     /* Move to the start */
  324.     Move(rp, left, top);
  325.  
  326.  
  327.  
  328.     /* Step through string */
  329.     for (i = 0; i < (len - 1); i++)
  330.     {
  331.         /* Is this an '_' ? */
  332.         if (label[i] == '_')
  333.         {
  334.             WORD            bot = (top + rp->TxHeight - rp->TxBaseline);
  335.             WORD            mark;
  336.  
  337.             /* Draw the first part of the string */
  338.             Text(rp, label, i);
  339.  
  340.             /* Remember where we are in the string */
  341.             mark = rp->cp_x;
  342.  
  343.             /* Draw the underscore */
  344.             Move(rp, mark, bot);
  345.             Draw(rp, (mark + TextLength(rp, &label[(i + 1)], 1L) - 2), bot);
  346.  
  347.             /* Return to where we were */
  348.             Move(rp, mark, top);
  349.  
  350.             /*
  351.              * Draw the rest of the string.  This one is done last so that the cursor
  352.              * could be positioned after the text.
  353.              */
  354.             Text(rp, &label[(i + 1)], (len - i - 1));
  355.  
  356.             /* Return the underlined character */
  357.             lod->lod_Key = (UWORD) label[i];
  358.         }
  359.     }
  360.  
  361.     /* Do we have an underscore? */
  362.     if (!lod->lod_Key)
  363.     {
  364.         /* Didn't find an '_' sign */
  365.         Text(rp, label, len);
  366.     }
  367.     return (1L);
  368. }
  369.  
  370.  
  371. UWORD
  372. GetLabelKeystroke(STRPTR label)
  373. {
  374.     LONG            count = (label) ? strlen(label) : 0L;
  375.     LONG            i;
  376.  
  377.     /* Search for an _ sign */
  378.     for (i = 0; i < (count - 1); i++)
  379.     {
  380.         /* Did we find an _ sign? */
  381.         if (label[i] == '_')
  382.         {
  383.             return ((UWORD) label[(i + 1)]);
  384.         }
  385.     }
  386.  
  387.     return (0);
  388. }
  389.  
  390.  
  391. /* TextExtent that honors the '_' as being a non-printable character (once) */
  392. WORD
  393. aTextExtent(struct RastPort * rp, STRPTR string, LONG count, struct TextExtent * te)
  394. {
  395.     WORD retval = FALSE;
  396.     STRPTR buffer;
  397.     LONG i;
  398.  
  399.     /* Allocate a temporary buffer */
  400.     if (buffer = AllocVec ((count + 1), MEMF_CLEAR))
  401.     {
  402.     /* Step through string */
  403.     for (i = 0; i < count; i++)
  404.     {
  405.             /* Is this an '_' sign? */
  406.             if (string[i] == '_')
  407.             {
  408.         /* Add the rest of the label to the buffer */
  409.         strcat (buffer, &string[(i + 1)]);
  410.  
  411.         /* Adjust the length of the string. */
  412.         count--;
  413.         break;
  414.         }
  415.         else
  416.         {
  417.         /* Copy each character over, until we reach the _ mark */
  418.         buffer[i] = string[i];
  419.         }
  420.         }
  421.  
  422.         /* Get the extent */
  423.         TextExtent(rp, buffer, count, te);
  424.  
  425.     /* Free the temporary buffer */
  426.     FreeVec (buffer);
  427.  
  428.     /* Show that we were successful */
  429.     retval = TRUE;
  430.     }
  431.  
  432.     /* Return whatever textextent returned */
  433.     return (retval);
  434. }
  435.  
  436. static          VOID
  437. getContentsExtent(Class * cl, Object * o, struct DrawInfo * drinfo)
  438. {
  439.     struct localObjData *lod = INST_DATA(cl, o);
  440.     struct TextExtent te =
  441.     {NULL};
  442.     struct RastPort rp;
  443.     STRPTR          label;
  444.  
  445.     /* maybe look at some flags to handle other types of text someday */
  446.     if (label = (STRPTR) IM(o)->ImageData)
  447.     {
  448.         /* Initialize the RastPort */
  449.         InitRastPort(&rp);
  450.  
  451.         if (lod->lod_Font)
  452.         {
  453.             SetFont(&rp, lod->lod_Font);
  454.         }
  455.         else if (drinfo && drinfo->dri_Font)
  456.         {
  457.             SetFont(&rp, drinfo->dri_Font);
  458.         }
  459.         /* Get the rectangle for the label */
  460.         aTextExtent(&rp, label, strlen(label), &te);
  461.  
  462.         /* Set the image structure */
  463.         IM(o)->Width = te.te_Width;
  464.         IM(o)->Height = te.te_Height;
  465.     }
  466.     else
  467.     {
  468.         IM(o)->Width = IM(o)->Height = 0;
  469.     }
  470. }
  471.